package logger

import (
	"bytes"
	"fmt"
	"gc-rds-ha/internal/common"
	"log"
	"os"
	"path/filepath"
	"sort"
	"strconv"
	"strings"

	"github.com/sirupsen/logrus"
	"gopkg.in/natefinch/lumberjack.v2"
)

// Formatter 日志格式
type Formatter struct {
	pid             string
	TimestampFormat string
}

// Format an log Entry
// Info level
// I0504 13:58:15.541 6159] hello world
func (f *Formatter) Format(entry *logrus.Entry) ([]byte, error) {
	// output buffer
	b := &bytes.Buffer{}
	// level
	level := strings.ToUpper(entry.Level.String())
	b.WriteString(level[:1])

	// time
	b.WriteString(entry.Time.Format(f.TimestampFormat))

	b.WriteString(" ")

	// pid
	b.WriteString(f.pid)

	// caller
	if entry.HasCaller() {
		f.writeCaller(b, entry)
	}

	// fields
	if len(entry.Data) > 0 {
		f.writeFields(b, entry)
	}

	// message
	b.WriteString("] ")
	b.WriteString(entry.Message)
	b.WriteByte('\n')
	return b.Bytes(), nil
}

func (f *Formatter) writeCaller(b *bytes.Buffer, entry *logrus.Entry) {
	fmt.Fprintf(b, " %s:%d:%s", filepath.Base(entry.Caller.File), entry.Caller.Line, entry.Caller.Function)
}

func (f *Formatter) writeFields(b *bytes.Buffer, entry *logrus.Entry) {
	if len(entry.Data) != 0 {
		fields := make([]string, 0, len(entry.Data))
		for field := range entry.Data {
			fields = append(fields, field)
		}

		sort.Strings(fields)

		for _, field := range fields {
			f.writeField(b, entry, field)
		}
	}
}

func (f *Formatter) writeField(b *bytes.Buffer, entry *logrus.Entry, field string) {
	fmt.Fprintf(b, " %v=%v", field, entry.Data[field])
}

func NewFormatter() *Formatter {
	return &Formatter{
		pid:             strconv.Itoa(os.Getpid()),
		TimestampFormat: "2006-01-02 15:04:05.123",
	}
}

// initLogger
func initLogger(logFilePath string, level logrus.Level, maxSize int, maxAge int, maxBackups int) error {
	logger := &lumberjack.Logger{
		Filename:   logFilePath,
		MaxSize:    maxSize, // 单个日志文件大小(MB)
		MaxAge:     maxAge,  // 单个日志文件最长生命同期
		MaxBackups: maxBackups,
		Compress:   true, // 轮转后的日志，启动gzip压缩
		LocalTime:  true, // 不用 UTC 时间
	}
	// 测试logger
	_, err := logger.Write([]byte{})
	if err != nil {
		return err
	}
	logrus.SetOutput(logger)
	logrus.SetLevel(level)
	if level == logrus.DebugLevel {
		logrus.SetReportCaller(true)
	}
	logrus.SetFormatter(NewFormatter())
	return nil
}

// InitLogger 初始化 Logger
func InitLogger(level logrus.Level) error {
	logFilePath := filepath.Join(common.GetLogDir(), fmt.Sprintf("%s.log", common.GetDateTimeInfo("formatDay")))
	// 单个文件500MB
	// 一天一日志
	// 保存一年日志
	return initLogger(logFilePath, level, 500, 1, 365)
}

func SetupLogger() {
	var err error
	if common.AgentConfig.Debug {
		err = InitLogger(logrus.DebugLevel)
	} else {
		err = InitLogger(logrus.InfoLevel)
	}

	if err != nil {
		log.Fatalf("初始化 logger 失败, err=%v", err)
	}
}
